/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.carparkweb.actionbeans;

import cz.muni.fi.pa165.carpark.TO.RoleTO;
import cz.muni.fi.pa165.carpark.TO.UserTO;
import cz.muni.fi.pa165.carpark.servicies.AuthorizationService;
import java.util.LinkedList;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Controller;

/**
 *
 * @author Martin
 */
@Controller
@UrlBinding("/auth/{$event}/{user.id}")
public class AuthorizationActionBean implements ActionBean {
    
    private static final Logger log = LoggerFactory.getLogger(AuthorizationActionBean.class);

    private ActionBeanContext context;
    
    @SpringBean
    @Qualifier("authorizationService")
    private AuthorizationService authorizationService;
    
     @ValidateNestedProperties(value = { 
            @Validate(on = {"createUser"}, field = "userName", required = true, minlength=3),  
            @Validate(on = {"createUser"}, field = "password", required = true, minlength=5),
    }) 
  
    private UserTO user = null;
    private String error = null;
    
    private Boolean vehicleAdmin = false;
    private Boolean employeeAdmin = false;

    public Boolean getUserCreated() {
        if(userCreated){
            this.userCreated = false;
            return true;
        }
        return userCreated;
    }

    public void setUserCreated(Boolean userCreated) {
        this.userCreated = userCreated;
    }
    
    private Boolean userExists = false;
    private Boolean userCreated = false;

    public Boolean getUserExists() {
        if(userExists){
            this.userExists = false;
            return true;
        }
        return userExists;
    }

    public void setUserExists(Boolean userExists) {
        this.userExists = userExists;
    }
    
    public Boolean getVehicleAdmin() {
        return vehicleAdmin;
    }

    public void setVehicleAdmin(Boolean vehicleAdmin) {
        this.vehicleAdmin = vehicleAdmin;
    }

    public Boolean getEmployeeAdmin() {
        return employeeAdmin;
    }

    public void setEmployeeAdmin(Boolean employeeAdmin) {
        this.employeeAdmin = employeeAdmin;
    }

    @DefaultHandler
    public Resolution addUser(){
        return new ForwardResolution("/WEB-INF/jsp/createUser.jsp");
    }
    
    public Resolution createUser() {
        log.debug("create user={},vehicle_adm={},employee_adm={}",this.user,this.vehicleAdmin,this.employeeAdmin);
        if (this.user != null) {
            try {
                this.user = authorizationService.retrieve(user.getUserName());
                for (RoleTO r : this.user.getRoles()) {
                    if (r.getAuthority().equals("vehicle_manager")) {
                        this.setVehicleAdmin(true);
                    }
                    if (r.getAuthority().equals("employee_manager")) {
                        this.setEmployeeAdmin(true);
                    }
                }
                this.userExists = true;
                this.userCreated = false;
             
            } catch (UsernameNotFoundException e) {
                // ok, user does not exist
                user.setRoles(new LinkedList<RoleTO>());
                if (this.employeeAdmin != null && this.employeeAdmin) {
                    RoleTO role = new RoleTO();
                    role.setAuthority("employee_manager");
                    user.getRoles().add(role);
                }
                if (this.vehicleAdmin != null && this.vehicleAdmin) {
                    RoleTO role = new RoleTO();
                    role.setAuthority("vehicle_manager");
                    user.getRoles().add(role);
                }

                this.authorizationService.create(user);
                this.userExists = false;
                this.userCreated = true;
            }
        }
        log.debug("created{},exist{}",this.userCreated,this.userExists);
        return new ForwardResolution("index.jsp");
    }

    public Resolution createSuperUser() {
        this.user = new UserTO();
        this.user.setRoles(new LinkedList<RoleTO>());
        RoleTO superadmin = new RoleTO();
        superadmin.setAuthority("superadmin");
        this.user.getRoles().add(superadmin);
        this.user.setPassword("admin");
        this.user.setUserName("admin");
        try {
            this.user = this.authorizationService.retrieve(user.getUserName());
            this.userExists = true;
        } catch (Exception e) {
            this.authorizationService.createSuper(user);
            this.userCreated = true;
        }
        return new ForwardResolution("/WEB-INF/jsp/createSuperUser.jsp");
    }
    
    public Resolution login(){
        error = context.getRequest().getParameter("error");        
        return new ForwardResolution("/WEB-INF/jsp/login.jsp");
    }  

    @Override
    public ActionBeanContext getContext() {
        return context;
    }

    @Override
    public void setContext(ActionBeanContext context) {
        this.context = context;
    }

    public UserTO getUser() {
        return user;
    }

    public void setUser(UserTO user) {
        this.user = user;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
}
